#include "DeviceBattery.h"
#include "common.h"

using namespace std;

//id:0x18FF01F3的处理函数
void anly1(unsigned char data[]){
    printf("======\n");
    float v = (data[0] + (data[1]<<8))*0.1;
    float I = (data[2] + (data[3]<<8))*0.1 - 3200;
    float soc = data[4] * 0.4;
    printf("电池组总压:%f; 电池组电流:%f; SOC:%f%%; ",v,I,soc);

    printf("电池组电压过充状态:");
    switch (data[5]&3){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("电池组总压偏高; ");
            break;
        case 2:
            printf("电池组总压过高; ");
            break;
        case 3:
            printf("电池过充; ");
            break;
        default:
            break;
    }

    printf("电池组电压过低状态:");
    switch ((data[5]>>2)&3){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("SOC低; ");
            break;
        case 2:
            printf("电池组总压过低; ");
            break;
        case 3:
            printf("电池过放; ");
            break;
        default:
            break;
    }

    printf("充电过流状态:");
    switch ((data[5]>>4)&3){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("电池充电或回馈电流轻度过流; ");
            break;
        case 2:
            printf("电池充电或回馈电流严重过流; ");
            break;
        case 3:
            printf("保留; ");
            break;
        default:
            break;
    }

    printf("放电过流状态:");
    switch ((data[5]>>6)&3){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("电池放电轻度过流; ");
            break;
        case 2:
            printf("电池放电严重过流; ");
            break;
        case 3:
            printf("保留; ");
            break;
        default:
            break;
    }

    printf("电池温度不均衡状态:");
    switch (data[6]&3){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("电池温差>10℃; ");
            break;
        case 2:
            printf("电池温差>20℃; ");
            break;
        case 3:
            printf("保留; ");
            break;
        default:
            break;
    }

    printf("温度过高状态:");
    switch ((data[6]>>2)&3){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("电池高温; ");
            break;
        case 2:
            printf("电池过温; ");
            break;
        case 3:
            printf("保留; ");
            break;
        default:
            break;
    }

    printf("电池低温状态:");
    switch ((data[6]>>4)&3){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("电池低温; ");
            break;
        case 2:
            printf("电池超低温; ");
            break;
        case 3:
            printf("保留; ");
            break;
        default:
            break;
    }

    printf("电池电压不均衡状态:");
    switch ((data[6]>>6)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("整组电压不均衡; ");
            break;
        default:
            break;
    }

    printf("BMS内部(自检)故障:");
    switch ((data[6]>>7)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("BMS内部从板检测或通信故障; ");
            break;
        default:
            break;
    }

    printf("\n");
    return ;
}

//id:0x18FF02F3的处理函数
void anly2(unsigned char data[]){
    printf("最大允许回馈电流:%f; 最大允许放电电流:%f; ",(data[0] + (data[1]<<8))*0.1,(data[2] + (data[3]<<8))*0.1);
    
    printf("整车状态:");
    switch (data[4]&3){
        case 0:
            printf("行车; ");
            break;
        case 1:
            printf("充电插头已连接; ");
            break;
        case 2:
            printf("充电插头已连接，且电池最低温＜10℃，禁止充电; ");
            break;
        case 3:
            printf("充电中; ");
            break;
        default:
            break;
    }

    printf("单体电池电压过充状态:");
    switch ((data[4]>>2)&3){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("单体电池电压偏高; ");
            break;
        case 2:
            printf("单体电池电压过高; ");
            break;
        case 3:
            printf("电池过充; ");
            break;
        default:
            break;
    }

    printf("单体电池电压过低状态:");
    switch ((data[4]>>4)&3){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("单体电池欠压; ");
            break;
        case 2:
            printf("单体电池电压过低; ");
            break;
        case 3:
            printf("电池过放; ");
            break;
        default:
            break;
    }

    printf("电池组最高温度:%f; ",(data[6])*0.5-20);
    printf("电池组最低温度:%f; ",(data[7])*0.5-20);

    printf("\n");
    return ;
}

//id:0x18FF03F3的处理函数
void anly3(unsigned char data[]){
    printf("最高单体电压:%f; 最低单体电压:%f; ",(data[0] + (data[1]<<8))*0.01,(data[2] + (data[3]<<8))*0.01);
    printf("最高单体电压编号:%d; ",data[4]);
    printf("最低单体电压编号:%d; ",data[5]);
    printf("最高温度编号:%d; ",data[6]);
    printf("最低温度编号:%d; ",data[7]);

    printf("\n");
    return ;
}

//id:0x18FF04F3的处理函数
void anly4(unsigned char data[]){
    printf("最高允许充电端电压高字节:%f; ",data[0]*0.1);
    printf("最高允许充电端电压低字节:%f; ",data[1]*0.1);
    printf("最高允许充电端电流高字节:%f; ",data[2]*0.1);
    printf("最高允许充电端电流低字节:%f; ",data[3]*0.1);
    printf("充电控制:");
    switch (data[4]&1){
        case 0:
            printf("充电开启; ");
            break;
        case 1:
            printf("电池保护，充电关闭; ");
            break;
        default:
            break;
    }

    printf("\n");
    return ;
}

//id:0x18FF05F3的处理函数
void anly5(unsigned char data[]){
    printf("正极母排温度:%f; ",data[0]*0.5-20);
    printf("负极母排温度:%f; ",data[1]*0.5-20);
    printf("侧扫供电温度:%f; ",data[2]*0.5-20);
    printf("载荷供电温度:%f; ",data[3]*0.5-20);
    printf("前扫供电温度:%f; ",data[4]*0.5-20);
    printf("航行供电温度:%f; ",data[5]*0.5-20);

    printf("下电信号状态:");
    switch (data[6]&1){
        case 0:
            printf("无下电信号; ");
            break;
        case 1:
            printf("有下电信号; ");
            break;
        default:
            break;
    }

    printf("充电信号状态:");
    switch ((data[6]>>1)&1){
        case 0:
            printf("无充电信号; ");
            break;
        case 1:
            printf("有充电信号; ");
            break;
        default:
            break;
    }
    printf("\n");
    return ;
}

//id:0x18FF06F3的处理函数
void anly6(unsigned char data[]){
    printf("SOH:%f; ",data[0]*0.4);
    
    printf("电池组温度差异状态:");
    switch (data[1]&3){
        case 0:
            printf("电池组温度差异正常; ");
            break;
        case 1:
            printf("电池组温度差异轻度偏高; ");
            break;
        case 2:
            printf("电池组温度差异严重偏高; ");
            break;
        case 3:
            printf("保留; ");
            break;
        default:
            break;
    }

    printf("热失控故障:");
    switch ((data[1]>>2)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("热失控; ");
            break;
        default:
            break;
    }

    printf("单体电压传感器故障:");
    switch ((data[1]>>3)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("单体电压传感器故障; ");
            break;
        default:
            break;
    }

    printf("温度传感器故障:");
    switch ((data[1]>>4)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("温度传感器故障; ");
            break;
        default:
            break;
    }

    printf("电流传感器故障:");
    switch ((data[1]>>5)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("电流传感器故障; ");
            break;
        default:
            break;
    }

    printf("整车CAN通信故障报警:");
    switch ((data[1]>>6)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("整车CAN通信故障; ");
            break;
        default:
            break;
    }

    printf("内网CAN通信故障报警:");
    switch ((data[1]>>7)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("内网CAN通信故障; ");
            break;
        default:
            break;
    }

    printf("与MCU通讯超时:");
    switch (data[2]&1){
        case 0:
            printf("电池组温度差异正常; ");
            break;
        case 1:
            printf("与MCU通讯超时; ");
            break;
        default:
            break;
    }

    printf("预充电异常报警:");
    switch ((data[2]>>1)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("预充电异常报警; ");
            break;
        default:
            break;
    }

    printf("绝缘报警（继电器闭合）:");
    switch ((data[2]>>2)&3){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("绝缘程度较低; ");
            break;
        case 2:
            printf("绝缘程度过低; ");
            break;
        case 3:
            printf("保留; ");
            break;
        default:
            break;
    }

    printf("主负继电器异常切断:");
    switch ((data[2]>>4)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("主负继电器异常切断; ");
            break;
        default:
            break;
    }

    printf("主正继电器带载切断:");
    switch ((data[2]>>5)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("主正继电器带载切断; ");
            break;
        default:
            break;
    }

    printf("主正和预充继电器粘连:");
    switch ((data[2]>>6)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("主负继电器粘连; ");
            break;
        default:
            break;
    }

    printf("主负继电器粘连:");
    switch ((data[2]>>7)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("主负继电器粘连; ");
            break;
        default:
            break;
    }

    printf("保险及其前端断路:");
    switch (data[3]&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("保险及其前端断路; ");
            break;
        default:
            break;
    }

    printf("电流均衡故障:");
    switch ((data[3]>>1)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("电流均衡故障; ");
            break;
        default:
            break;
    }

    printf("单体电压不均衡:");
    switch ((data[3]>>2)&3){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("单体电压不均衡程度高; ");
            break;
        case 2:
            printf("单体电压不均衡程度偏高; ");
            break;
        case 3:
            printf("单体电压不均衡程度过高; ");
            break;
        default:
            break;
    }

    printf("PACK检测故障:");
    switch ((data[3]>>4)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("PACK检测故障; ");
            break;
        default:
            break;
    }

    printf("DCLink检测故障:");
    switch ((data[3]>>5)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("DCLink检测故障; ");
            break;
        default:
            break; 
    }

    printf("主正继电器无法吸合:");
    switch ((data[3]>>6)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("主正继电器无法吸合; ");
            break;
        default:
            break;
    }

    printf("主负继电器无法吸合:");
    switch ((data[3]>>7)&1){
        case 0:
            printf("正常; ");
            break;
        case 1:
            printf("主负继电器无法吸合; ");
            break;
        default:
            break;
    }

    printf("电池包内互锁故障:");
    switch (data[4]&3){
        case 0:
            printf("互锁正常; ");
            break;
        case 1:
            printf("检测不到互锁信号; ");
            break;
        case 2:
            printf("互锁信号先有后无; ");
            break;
        case 3:
            printf("保留; ");
            break;
        default:
            break;
    }

    printf("SOC低报警:");
    switch ((data[4]>>2)&3){
        case 0:
            printf("SOC正常; ");
            break;
        case 1:
            printf("SOC偏低; ");
            break;
        case 2:
            printf("SOC中度偏低; ");
            break;
        case 3:
            printf("SOC严重偏低; ");
            break;
        default:
            break;
    }

    printf("SOC高报警:");
    switch ((data[4]>>4)&1){
        case 0:
            printf("SOC正常; ");
            break;
        case 1:
            printf("SOC偏高; ");
            break;
        default:
            break;
    }

    printf("SOH低报警:");
    switch ((data[4]>>5)&1){
        case 0:
            printf("SOH正常; ");
            break;
        case 1:
            printf("SOH偏高; ");
            break;
        default:
            break;
    }

    printf("\n");
    printf("======\n");
    return ;
}

void DeviceBattery::func(Battery_data& data) {
    try {
        int &s = m_fd; // 用于CAN通信的socket文件描述符
        int ret; // 用于存储函数的返回值

        struct can_frame frame; // 用于存储接收到的CAN帧
        for(int i = 0; i < 6;i++){
            // 对收到的消息进行处理
            ret = read(s,&frame,sizeof(frame));
            
            if(ret < 0){
                perror("read error");
                close(s);
                return ;
            } else if (ret == 0) {
                printf("No data received\n");
                close(s);
                return ;
            }

            // 根据CAN帧的ID进行不同的处理
            switch (frame.can_id & CAN_EFF_MASK){
                case 0x18FF01F3:{
                    // anly1(frame.data,data);
                    float v = ((float)frame.data[0] + (float)(frame.data[1]<<8))*0.1;
                    float I = ((float)frame.data[2] + (float)(frame.data[3]<<8))*0.1 - 3200;
                    float soc = frame.data[4] * 0.4;

                    data.I = I;
                    data.v = v;
                    data.soc = soc;
                    
                    break;
                }
                case 0x18FF02F3:
                    // anly2(frame.data);
                    break;
                case 0x18FF03F3:
                    // anly3(frame.data);
                    break;
                case 0x18FF04F3:
                    // anly4(frame.data);
                    break;
                case 0x18FF05F3:
                    // anly5(frame.data);
                    break;
                case 0x18FF06F3:
                    // anly6(frame.data);
                    break;
                default:
                    printf("Unknown CAN ID: 0x%X\n", frame.can_id);
                    break;
            }
        }

        // printf("v = %f, I = %f, soc = %f\n",data.v,data.I,data.soc);
    } catch (const exception& e) {
        cerr << "Error in DeviceBattery::func: " << e.what() << endl;
    }

}

DeviceBattery::DeviceBattery(const string& interfaceName, const string& dt) {
    deviceName = interfaceName;
    deviceType = dt;

    m_fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if (m_fd < 0) {
        throw system_error(errno, generic_category(), "Failed to create CAN socket");
    }

    ifreq ifr;

    strcpy(ifr.ifr_name, deviceName.c_str());

    // 获取网络接口的索引值
    if (ioctl(m_fd, SIOCGIFINDEX, &ifr) < 0) {
        int err = errno;
        close(m_fd);
        throw system_error(err, generic_category(), "Failed to get interface index");
    }

     // 初始化CAN地址结构体
    sockaddr_can addr;
    addr.can_family = AF_CAN; // 设置地址族为CAN
    addr.can_ifindex = ifr.ifr_ifindex; // 设置接口索引

    // 绑定socket到指定的CAN接口
    if (bind(m_fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) {
        int err = errno;
        close(m_fd);
        throw system_error(err, generic_category(), "Failed to bind CAN socket");
    }
}

DeviceBattery::~DeviceBattery() {
    close(m_fd);
    m_fd = -1;
}